<?php

namespace App\Http\Controllers;

use App\Models\Comment;
use App\Models\Mechanic;
use App\Models\Phone;
use App\Models\Post;
use App\Models\Product;
use App\Models\Role;
use App\Models\User;

class EloquentController extends Controller
{
    /**
     *  一对一
     *  正向获取关联关系
     */
    public function forwardOneToOneInfo()
    {
        $user = User::find(1); // find() 方法获取的都是一个相关的模型，不是 Eloquent 模型集合。

        // 通过动态属性获取正向关联数据
        $dynamic_property_data = $user->phone; // (一对一正向) 获取用户对应的手机信息

        // 通过链式查询返回手机信息，链式调用可以使用查询构造器的 条件搜索，字段过滤等操作。
        $chain_query_single_data = $user->phone()->select('id', 'user_id', 'number')->first();

        return response()->json(compact('dynamic_property_data', 'chain_query_single_data'));
    }

    /**
     *  一对一
     *  反向获取关联关系
     */
    public function reverseOneToOneInfo()
    {
        $phone = Phone::find(1); // find() 方法获取的都是一个相关的模型，不是 Eloquent 模型集合。

        // 通过动态属性获取反向关联数据
        $dynamic_property_data = $phone->user;

        // 通过链式查询方式获取反向关联数据，链式调用可以使用查询构造器的 条件搜索，字段过滤等操作。
        $chain_query_single_data = $phone->user()->select('id', 'name', 'email')->first();

        return response()->json(compact('dynamic_property_data', 'chain_query_single_data'));
    }

    /**
     *  一对多
     *  正向获取关联关系
     */
    public function forwardOneToManyInfo()
    {
        $post = Post::find(1); // find() 方法获取的都是一个相关的模型，不是 Eloquent 模型集合。

        // 通过动态属性的方式正向获取关联数据，返回关联的所有条目的全字段数据
        $dynamic_property_data = $post->comments; // (一对一正向) 获取用户对应的手机信息

        // 通过链式调用的方式正向获取关联数据，链式调用可以使用查询构造器的 条件搜索，字段过滤等操作。
        $query = $post->comments()->select('id', 'post_id', 'content');
        // 获取多条数据，关联查询 hasMany 没有 order() 方法，这里不能排序
        $chain_query_multi_data = $query->get();
        // 获取单条数据，关联查询 hasMany 没有 order() 方法，这里不能排序
        $chain_query_single_data = $query->where('content', 'like', '%美好%')->first();

        return response()->json(compact('dynamic_property_data', 'chain_query_multi_data', 'chain_query_single_data'));
    }

    /**
     *  一对多
     *  反向获取关联关系
     */
    public function reverseOneToManyInfo()
    {
        $comment = Comment::find(1);

        // 通过动态属性的方式获取关联数据，返回关联的所有条目的全字段数据
        $dynamic_property_data = $comment->post;

        // 通过链式查询获取反向关联数据
        $query = $comment->post()->select('id', 'title');
        //（在这里是返回一条）
        // 获取单条数据，关联查询 hasMany 没有 order() 方法，这里不能排序
        $chain_query_single_data = $query->first();

        return response()->json(compact('dynamic_property_data', 'chain_query_single_data'));
    }

    /**
     *   默认模型，如果当 belongsTo，hasOne，hasOneThrough 和 morphOne 对应关系找不到数据，它会返回 null
     */

    /**
     *  belongsTo 查询所属关系的子模型数据
     */
    public function belongsToByObject()
    {
        // 反向一对一，通过传入父模型对象，查询与之相关的子模型数据，链式调用可以使用查询构造器的 条件搜索，字段过滤等操作。
        $user = User::find(1);
        $phone_data = Phone::whereBelongsTo($user)->select('id', 'user_id', 'price', 'number')->get();

        // 反向一对多，通过传入父模型对象，查询与之相关的子模型数据，链式调用可以使用查询构造器的 条件搜索，字段过滤等操作。
        $post = Post::find(1);
        $comment_data = Comment::whereBelongsTo($post)->select('id', 'post_id', 'content')->get();

        return response()->json(compact('phone_data', 'comment_data'));
    }

    /**
     *  hasMany 检索对应最新或最早的一条数据
     */
    public function hasOneOfMany()
    {
        $post = Post::find(1);
        // 获取博客最新的一条评论，返回一条数据
        // 这里筛选返回字段的时候，一定要指定字段和表名的所属关系，要不然会报错提示：column '**' in field list is ambiguous
        $comment_latest_data = $post->latestComment()->select('comments.id', 'comments.post_id', 'comments.content')->first();

        // 获取博客最早的一条评论，返回一条数据
        // 这里筛选返回字段的时候，一定要指定字段和表名的所属关系，要不然会报错提示：column '**' in field list is ambiguous
        $comment_oldest_data = $post->oldestComment()->select('comments.id', 'comments.post_id', 'comments.content')->first();

        // 获取当前商品的最新定价记录
        $product = Product::find(1);
        // 这里筛选返回字段的时候，一定要指定字段和表名的所属关系，要不然会报错提示：column '**' in field list is ambiguous
        $current_product_price = $product->currentPrice()->select('prices.id', 'prices.product_id', 'prices.price')->first();

        return response()->json(compact('comment_latest_data', 'comment_oldest_data', 'current_product_price'));
    }

    /**
     *  远程一对一
     *  正向获取关联关系
     */
    public function forwardRemoteOneToOneInfo()
    {
        // 获取机械id=1 分类的所有机主信息
        $mechanic = Mechanic::find(1);
        // 通过动态属性获取关联数据
        $dynamic_property_car_owner_data = $mechanic->carOwner;
        // 通过链式查询获取关联数据
        $chain_query_car_owner_data = $mechanic->carOwner()->select('owners.id', 'owners.name')->get();
        // 通过with，预加载获取关联数据
        $with_data = $mechanic->with('carOwner')->get();

        return response()->json(compact('dynamic_property_car_owner_data', 'chain_query_car_owner_data', 'with_data'));
    }

    /**
     *  远程一对多
     *  正向获取关联关系
     */
    public function forwardRemoteOneToManyInfo()
    {
        // 获取机械id=1 分类的所有机主信息
        $mechanic = Mechanic::find(1);
        // 通过动态属性获取关联数据
        $dynamic_property_car_owner_data = $mechanic->carOwners;
        // 通过链式查询获取关联数据
        $chain_query_car_owner_data = $mechanic->carOwners()->select('owners.id', 'owners.name')->get();
        // 通过with，预加载获取关联数据
        $with_data = $mechanic->with('carOwners')->get();

        return response()->json(compact('dynamic_property_car_owner_data', 'chain_query_car_owner_data', 'with_data'));
    }

    /**
     * 多对多
     * 正向获取关联关系
     */
    public function forwardManyToManyInfo()
    {
        $user = User::find(1);
        // 通过动态属性获取所有关于此用户的角色
        $dynamic_property_roles_data = $user->roles;

        // 获取中间表字段
        $dynamic_property_middle_data = [];
        foreach ($user->roles as $role) {
            $arr['name'] = $role->pivot->name;
            $arr['created_at'] = $role->pivot->created_at;
            $dynamic_property_middle_data[] = $arr;
        }

        // 通过链式查询获取角色信息
        $link_query_roles_data = $user->roles()->get();

        // 获取中间表字段
        $link_query_middle_data = [];
        foreach ($dynamic_property_roles_data as $role) {
            $arr['name'] = $role->pivot->name;
            $arr['created_at'] = $role->pivot->created_at;
            $link_query_middle_data[] = $arr;
        }

        // 通过 with 方法预加载角色信息
        $with_roles_data = $user->with('roles')->first();

        return response()->json(compact('dynamic_property_roles_data', 'link_query_roles_data', 'with_roles_data', 'dynamic_property_middle_data', 'link_query_middle_data'));
    }

    /**
     * 多对多
     * 反向获取关联关系
     */
    public function reverseManyToManyInfo()
    {
        $role = Role::find(1);
        // 通过动态属性获取所有关于此角色的用户
        $dynamic_property_user_data = $role->user;

        // 通过链式查询获取用户信息
        $link_query_user_data = $role->user()->get();

        // 通过 with 方法预加载用户信息
        $with_user_data = $role->with('user')->first();

        return response()->json(compact('dynamic_property_user_data', 'link_query_user_data', 'with_user_data'));
    }
}
